refactor(spec)!: 退役 activationEvents(两处键)与 ActivationEventSchema 词表 —— 四仓零 runtime reader 的惰性激活声明 (#4657) - #4831
Conversation
…onEventSchema vocabulary (#4657, ADR-0049) Lazy plugin activation was declared on two authorable surfaces and implemented by no runtime in any repo — every plugin activates immediately on load/registration. Enforce-or-remove, ruled remove: - kernel DynamicLoadRequest.activationEvents → retiredKey() tombstone (non-strict schema; a plain delete would strip silently) - studio StudioPluginManifest.activationEvents → strict-parse guidance prescription (with the former activation/events/onActivate aliases) - ActivationEventSchema / ActivationEvent def deleted from ./kernel and ./studio (orphaned value schema, #3950); manifest + authorable-surface baseline lines dropped deliberately (#4650 route: defs no longer emitted / def not root-reachable — gate-adjudicated) - ADR-0087 D3 semantic migration plugin-activation-events-retired (no sys_metadata source exists for a D2 rewrite) - compiler-API export pin with anti-vacuity guards; docs + changeset Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
…ivation-events-retirement
Ratchet files reset to origin/main and regenerated (never textually merged); the delta vs main is exactly this PR's intent — 2 manifest def removals, 6 authorable lines dropped / 1 [RETIRED], 4 api-surface export removals — and #4616's system/*Template*/*Notification* deletions remain absent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
…ivation-events-retirement
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
CI:
|
`packages/spec/spec-changes.json` 与 `docs/protocol-upgrade-guide.md` 在 `.gitattributes` 里走 `merge=os-regen`。合并 origin/main(含 #4831 退役 activationEvents)后实测:两文件**零冲突标记**地只保留了本分支一侧 —— `plugin-activation-events-retired` 被静默吞掉(`grep -c` = 0),正是 #4616 预警的失效形态。 按规矩不做文本合并:`git checkout origin/main --` 取回两文件后,从合并后的 **源**(`conversions/registry.ts` 的 summary + `migrations/registry.ts` 的 step17.semantic)整体重新生成,得到正确并集。 重生成后核对:两条条目并存;#4616 的四个删除(system/EmailTemplate、 SMSTemplate、PushNotification、InAppNotification)未复活,幸存的 EmailTemplateDefinition 仍在;#4657/#4831 的 kernel/studio ActivationEvent def 与 ActivationEventSchema 导出未复活,authorable-surface 里 activationEvents 仅剩 #4831 自己的 `[RETIRED]` 墓碑行。五张 ratchet 重生成后与 main 逐字节一致, 本分支一张未动。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
os-regen 合并驱动对 spec-changes.json / protocol-upgrade-guide.md 不做文本合并, 本次合并零冲突标记地只保留了本分支一侧,静默吞掉 #4657 的条目(实测: origin/main 的 spec-changes.json 含 4 条 activationEvents 条目,合并后为 0)。 按协议 git checkout origin/main -- <生成物> 后从合并后的源整体重新生成: - spec-changes.json:现同时含 #4657 的 activationEvents 4 条与本单 batch-row-result-schema-shape 2 条 - protocol-upgrade-guide.md:同时含 plugin-activation-events-retired 与 batch-row-result-schema-shape - 四张 ratchet(api-surface / api-surface-signatures / authorable-surface / json-schema.manifest)与 origin/main 逐字节相同 —— 本单不增删任何导出 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
Fixes #4657
裁决与事实
ADR-0049 enforce-or-remove,走 remove(v17 破坏窗口内,
.changeset/pre.json仍mode: pre)。activationEvents在两个可创作面上承诺惰性激活("plugins remain dormant until an activation event fires"):DynamicLoadRequest.activationEvents(@objectstack/spec/kernel)StudioPluginManifest.activationEvents(@objectstack/spec/studio,defineStudioPlugin入参)四仓(objectstack / cloud / cloud-v1 / objectui)没有任何 runtime reader。 实施时按裸名重扫(不是 import 扫描 —— #4616 的教训):objectstack 全仓命中仅 spec 自身源码/测试、生成物、历史 CHANGELOG 与
packages/vscode-objectstack/package.json(VS Code 自己的字段,不碰);objectui 唯一命中是packages/vscode-extension/package.json(同上);cloud 唯一命中是一条 changeset 散文。cloud-v1 ROADMAP 自记 ❌ 未实现(v0.4.0 计划)。所有插件从来都是安装即激活 —— 这个键在语义上撒谎,作者写activationEvents: [{ type: 'onMetadataType', pattern: 'flow' }]期待延迟加载,拿到的是立即激活加一次干净的 parse。与 #4653 的同 major 合成:#4653 刚在同一个未发布 major 里把双源收敛到结构化形状;裁决落在 remove,该收敛词表在发布前退役。对 v16 作者合成后的迁移就是一句话:删掉这个键,无论你拿的是哪种形状。行为零变化(前后都是 eager)。#4653 未登记任何 conversion,无可吸收项;其 changeset 不动(已在 main)。
退役形态(按门禁实跑输出裁定,非照抄先例)
gen:schema的 #4650 门禁实报(merge 后基线023c00b5590d):据此三处三种形态:
retiredKey()墓碑(feat(spec)!: 退役 DriverCapabilities 31 个零读者能力位 —— 全表活性审计,3 活 31 死(#4634,ADR-0049) #4783 谱系)。DynamicLoadRequestSchema非.strict(),裸删 = Zod 静默 strip(fix(showcase): register Mark Done action handler via inline body #2169 形状);墓碑让删除在tsc(input 为never)和 parse(处方本身)两个通道都可听见。authorable-surface.json该行转为[RETIRED],gate (b) 由 D3 semantic surface 满足。StudioPluginManifestSchema是strictObject,删键后 strict parse 拒绝,guidance携带处方。原三个 VS Code 味 alias(activation/events/onActivate)一并移入 guidance 同一处方 —— alias 决不能指向 schema 无法接受的键(triggerPhrasessuggester 陷阱)。基线行删除由 authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650 路线 2 放行(def 不可达 metadata-type 根,见上方实报)。ActivationEventSchema/ActivationEventdef → 整体删除(authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650 路线 3,spec/system 通知模板语汇在 C3 后成为零消费方孤儿:EmailTemplate/SMSTemplate/PushNotification/InAppNotification(Schema) 待 enforce-or-remove 处置 #4616 谱系)。两个父键都退役后 def 是孤儿值 schema —— 有导出无消费者会被读成能力(refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950);kernel/ActivationEvent、studio/ActivationEvent两个 manifest 条目与 4 条 authorable 行有意删除,由 manifest ratchet(gen:schema silently drops PageTabsProps since #2967 — references regen would delete real docs #2978)与check:api-surface裁定(见上方实报第二、三条)。ADR-0087 conversion 逐条评估
D2 不适用。 D2 重写的是 load path 上的
sys_metadata存量行/stack 源:StudioPluginManifest是 TS config(defineStudioPlugin入参,root schema,从不入 stack 树 —— 对照 #4579RestServerConfig.openApi31的同款论证);DynamicLoadRequest是 runtime 请求形状,且四仓零 caller。不存在任何可被 D2 改写的存量源,登记 D2 会是给不存在的输入写变换(fixture 也无从取真)。D3 登记:
plugin-activation-events-retired(migrations/registry.tsstep17.semantic),surfacekernel.dynamicLoadRequest.activationEvents / studio.studioPluginManifest.activationEvents(两个 clause 都以键名结尾,满足 gate (b) 的 endsWith 匹配),reason/acceptanceCriteria非空,并扩写 step17rationale。对照:#4734 需要 D2(有存量可改写)—— 本单没有;#4767 / #4783 / #4616 不需要 D2 —— 本单同类,且与 #4579(plugin TS config)、#4618(nothing ever parsed it,def 整删 + 基线有意删)两个先例逐点同构。Pin 与 sabotage 实跑
新增
packages/spec/src/kernel/activation-events-retirement.test.ts:compiler API 符号身份路线 —— exports-map 枚举全部入口(> 10 防空转)、module symbol 必须 resolve(防空转守卫)、holdersOf(name)精确相等[](两个退役名在所有公共入口零 holder)、幸存邻居(DynamicLoadRequestSchema/StudioPluginManifestSchema)仍在(> 40 导出面防空转)、runtime namespace 一致性、live path 正反向 parse。另在plugin-runtime.test.ts/plugin.test.ts各有处方负向 pin(.toThrow(/activationEvents.*removed.*#4657/s))与not.toHaveProperty正向 pin(absence 不物化)。三轮 sabotage 全部实跑、全部红、全部已还原:
ActivationEventSchema):AssertionError: ActivationEventSchema must have zero holders: expected [ './kernel' ] to deeply equal []+ runtime 断言同红(2 failed)。./studio把StudioPluginContributionsSchema以退役名 re-export):AssertionError: ActivationEventSchema must have zero holders: expected [ './studio' ] to deeply equal [](2 failed)。AssertionError: ./kernel module symbol must resolve: expected undefined to be truthy—— 守卫先红,断言不会空转通过。连带面
studio/plugin.zod.tsalias hints 与dependencies提示语改写(不再指向已删键);studio/index.tsre-export 删除;两处 zod 文件均留 REMOVED 注释指明活机制(eager)。content/docs/plugins/development.mdx:os:check 示例删键,"Activation Events" 小节(仍在教 pre-v17 字符串词表)改为 eager 事实陈述 + 处方;check:skill-examples对 built dist 编译通过。packages/spec/PLUGIN_STANDARDS.md两处更新;references 文档由gen:docs重生(studio/plugin-runtime.mdx整页随 def 消失)。.changeset/retire-activation-events.md(@objectstack/spec: major),按 ✅ spec 双源清账主单:基线 52 → 0(2026-08-03 收官)—— #4446 gate 落地后的偿还 worklist #4535 §5 三问自证:TS2305 有(两入口两导出);元数据迁移无(无存量可改写,D3 记录);形状变更两键删除、行为零变化。FROM → TO 明写"删掉该键;所有插件本来就是安装即激活"。content/docs/releases/未触碰。**不碰三个 VS Code 扩展的package.json。Main 同步
实施期间 main 前进两次,均
git merge origin/main(未 rebase / 未 force-push):023c00b5(spec/system 通知模板语汇在 C3 后成为零消费方孤儿:EmailTemplate/SMSTemplate/PushNotification/InAppNotification(Schema) 待 enforce-or-remove 处置 #4616 / PR feat(spec)!: 通知模板孤儿语汇退役 —— ./system 不再导出 EmailTemplate/SMSTemplate/PushNotification/InAppNotification (#4616) #4809 合入 —— 预警过的并行单):四张 ratchet 全部git checkout origin/main --后在合并源上整体重新生成,非文本合并;并断言 spec/system 通知模板语汇在 C3 后成为零消费方孤儿:EmailTemplate/SMSTemplate/PushNotification/InAppNotification(Schema) 待 enforce-or-remove 处置 #4616 删除的system/EmailTemplate/SMSTemplate/PushNotification/InAppNotification(精确名)未被复活,同时区分幸存的system/EmailTemplateDefinition(不同 def,合法存活)。对 main 的 delta 精确等于本 PR 意图:manifest −2 def、authorable −6 行 +1[RETIRED]、api-surface −4 导出。cb680f27(纯 docs,两文件,与本 diff 零交集):直接合并。验证读数(全部在合并源上实跑)
gen:schemacheck:generatedcheck:authorable-surface/check:api-surface/check:docs/check:spec-changes/check:upgrade-guide/check:skill-refs/check:skill-docscheck:dual-source-exportscheck:liveness/check:empty-state/check:skill-examples/check:exported-any/check:react-declaration-parity)check:doc-authoring/check:adr-anchors/check:i18n/check:nul-bytes)liveness ledger 无涉(两父 schema 均非 metadata-type,ledger 无对应行,
check:livenessPASS 佐证);forms / i18n bundle 无涉(无*.form.ts输入引用该键,check:i18nPASS);CLI advisory lint ledger 驱动,无行即无 warn。范围外发现
packages/spec/PLUGIN_STANDARDS.md§5.3 仍在罗列 #3896 follow-up 已删除的PluginDiscoveryConfigSchema/DynamicLoadingConfigSchema(本 PR 只改了自己范围内的ActivationEventSchema行),连同DynamicLoadRequest家族"零 runtime consumer、是否整族 enforce-or-remove"的悬置问题,已另行立案(见 issue 评论区链接)。🤖 Generated with Claude Code
https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
Generated by Claude Code